#include <stdio.h>
#include <stdlib.h>
#include "Includes/Color.h"
#include "Includes/Matrix.h"
#include "Includes/Rectangle.h"
#include "Includes/Surface.h"
#include "Includes/Context.h"
#include "Includes/Defines.h"
#include "Includes/Driver.h"
#include <unistd.h>
#include <string.h>

/// <summary>
/// TODO
/// </summary>
SurfacePtr GalCreateSurface(void)
{
	SurfacePtr surface;
	if (!(surface = (SurfacePtr)malloc(sizeof(Surface))))
		return NULL;

	surface->width = 0;
	surface->height = 0;
	surface->stride = 0;
	surface->private = NULL;
	surface->refcount = 1;
	surface->data = NULL;
	surface->bpp = 0;

	return surface;
}

/// <summary>
/// TODO
/// </summary>
SurfacePtr GalCreateMemorySurface(int detph, int width, int height)
{
	if (detph < 32)
		return NULL;

	if (width < 1 || height < 1)
		return NULL;

	SurfacePtr surface;
	if (!(surface = (SurfacePtr)malloc(sizeof(Surface))))
		return NULL;

	surface->width = width;
	surface->height = height;
	surface->stride = width * 4;
	surface->size = ((width * 4) * height);
	surface->data = malloc((width * 4) * height);
	surface->type = GAL_SURFACE_SYSTEMMEMORY;
	surface->refcount = 1;
	surface->private = NULL;
	surface->bpp = 32;
	memset(surface->data, 255, surface->size);

	return surface;
}

/// <summary>
/// Creates a Surface object
/// based on an array of bytes along
/// with size and format information.
/// </summary>
SurfacePtr GalCreateSurfaceFromData(unsigned char *data, int width, int height, int stride)
{
	if (data == NULL)
		return NULL;

	if (width < 1 || height < 1)
		return NULL;

	SurfacePtr surface;
	if (!(surface = (SurfacePtr)malloc(sizeof(Surface))))
		return NULL;

	surface->width = width;
	surface->height = height;
	surface->stride = stride;
	surface->type = GAL_SURFACE_DATA;
	surface->refcount = 1;
	surface->private = NULL;
	surface->data = data;
	surface->bpp = 32;

	return surface;
}

/// <summary>
/// TODO
/// </summary>
SurfacePtr GalCreateWindowSurface(void)
{
	SurfacePtr surface;
	if (!(surface = GalCreateSurface()))
		return NULL;
	surface->width = 0;
	surface->height = 0;
	return surface;
}

/// <summary>
/// TODO
/// </summary>
SurfacePtr GalCreateDisplaySurface(void)
{
	SurfacePtr surface;
	if (!(surface = GalCreateSurface()))
		return NULL;

	surface->width = 0;
	surface->height = 0;

	return surface;
}

/// <summary>
/// TODO
/// </summary>
int GalSurfaceBlit(SurfacePtr dst, SurfacePtr src, RectanglePtr clip, int x, int y)
{
	if (dst == NULL)
		return -1;
		
	if (src == NULL)
		return -1;

	//if (clip == NULL)
	//	return -1;

    int w1 = (dst->width);
    int h1 = (dst->height);
    int w2 = (src->width);
    int h2 = (src->height);
    int xd = ((x < 0)) ? 0 : x;
    int yd = ((y < 0)) ? 0 : y;
    int xs = ((x < 0)) ? (0 - x) : 0;
    int ys = ((y < 0)) ? (0 - y) : 0;
	int xc = ((x + w1) > w2) ? (w1 - ((x + w1) - w2) - xs) : (w1 - xs);
	int yc = ((y + h1) > h2) ? (h1 - ((y + h1) - h2) - ys) : (h1 - ys);

	/*    
	unsigned char* s = src + (xs * 4) + (ys * p1);
	unsigned char* d = dst + (xd * 4) + (yd * p2);
*/
	return 0;
}

/// <summary>
/// TODO
/// </summary>
void* GalMapSurface(SurfacePtr surface)
{
	if (surface == NULL)
		return NULL;

	return NULL;
}

/// <summary>
/// TODO
/// </summary>
int GalUnmapSurface(SurfacePtr surface)
{
	if (surface == NULL)
		return -1;

	return 0;
}

/// <summary>
/// TODO
/// </summary>
int GalSurfaceDestroy(SurfacePtr surface)
{
	if (surface == NULL)
		return -1;

	if (surface->type == GAL_SURFACE_SYSTEMMEMORY)
		free(surface->data);

	free(surface);
	return 0;
}
